Computer systems, in general, include a main memory (also known as the computer's “physical memory”) for storing data and instructions of currently executing programs (“process threads”). Typically, the main memory is organized as a plurality of sequentially numbered storage units, each containing a fixed size quantity (e.g. an 8-bit byte in byte oriented computers). The numbering of the storage units (typically in binary or hexadecimal values starting from zero up to the total number of storage units minus one) serve as addresses by which a particular storage unit can be referenced for reading or writing the data contained therein. The set of numbers by which the storage units are addressed is known as the “physical address space” of the main memory. Main memory typically is realized using semiconductor memory which provides fast, random-access to the various storage units, but requires constant application of electrical energy for operation (i.e. the memory is volatile).
Computer systems also typically provide one or more secondary storage or memory devices which are generally slower than the main memory, but have a much greater storage capacity than the main memory. The secondary storage devices typically store data on a magnetic or optical media that is non-volatile, such as a hard disk. Secondary storage devices generally store data in the form of files or sequential data streams.
Due to the greater speed at which data can be accessed in main memory, data that is currently in use by process threads running on the computer system is desirably stored in the main memory. Due to the smaller storage capacity of the main memory, however, main memory may be unable to store all the information needed by process threads. Accordingly, data that is no longer currently in use is desirably removed from the main memory, or moved from the main memory to the secondary storage devices.
Techniques to efficiently manage the use of the main memory (“memory management techniques”) by process threads are conventionally known. One standard technique, commonly known as “virtual memory,” is implemented by many operating systems, usually in cooperation with a computer system's processor. Virtual memory techniques create a separate address space, referred to as the “virtual address space” or “process address space” by which process threads access data in memory. The operating system and processor translates or maps a subset of the virtual addresses in the virtual address space to actual physical addresses in the main memory's physical address space. When a process thread reads or writes data to a virtual address in its virtual address space, the operating system and/or processor translates the virtual address to a corresponding physical address of a storage unit in the main memory where the data is to be read or written. In Microsoft Corporation's Windows NT operating system, for example, a component called the virtual memory manager implements a separate virtual address space for each process in cooperation with the computer's processor.
Since the virtual address space is typically much larger than the physical address space of the main memory, only a subset of the virtual address space can be resident in main memory at one time. Data not resident in main memory is temporarily stored in a “backing store” or “paging” file on the computer's hard disk. When the main memory becomes over committed (i.e. its storage capacity is exceeded), the operating system begins swapping some of the contents of the main memory to the “backing store” file. When the data is again required by a process thread, the operating system transfers the data back into the main memory from the backing store file. By swapping data that is no longer needed to the hard disk, virtual memory allows programmers to create and run programs that require more storage capacity than is available in the main memory alone.
Moving data between the main memory and the hard disk is most efficiently performed in larger size blocks (as compared to bytes or words). Accordingly, virtual memory techniques generally perform swapping in large size blocks. Microsoft Corporation's Windows NT operating system, for example, divides the virtual address space of each process thread into equal size blocks referred to as “pages.” The main memory also is divided into similar size blocks called “page frames,” which contain the pages mapped into the main memory. The page size in the Windows NT operating system can vary depending on the requirements of the particular computer on which it is run.
In the Windows NT operating system, each process has a set of pages from its virtual address space that are present in physical memory at any given time. Pages that are currently in the main memory and immediately available are termed “valid pages.” Pages that are stored on disk (or in memory but not immediately available) are called “invalid pages.” When an executing thread accesses a virtual address in a page marked “invalid”, the processor issues a system trap called a “page fault.” The operating system then locates the required page on the hard disk and loads it into a free page frame in the main memory. When the number of available page frames runs low, the virtual memory system selects page frames to free and copies their contents to the hard disk. This activity, known as “paging,” is imperceptible to the programmer.
One of the problems that continues to confront so-called paging operating systems, such as the one described above, concerns the treatment of sensitive information (e.g. passwords to access network resources, credit card information used during an Internet shopping session, and the like). For example, when an individual, using a password, logs onto an operating system such as Windows NT, the individual's password can typically be kept in memory for various reasons. For example, if the user locks a work station and wants to later unlock it, the operating system needs to validate against something. Thus, the operating system goes out to main memory and compares what is typed in by a user with what is sitting in the memory. Between these two points in time, however, the password may have entered the paging file because the operating system may have decided that the logon process was idle. Having the password in the paging file can leave it open to attack, e.g. if the machine on which the paging file is located were to be physically stolen. Thus, because of the nature of paging operating systems, sensitive information can sometimes be undesirably placed in a paging file in secondary memory. In security-sensitive installations, preventing the sensitive information from reaching the paging file may be advantageous.
There have been attempts in the past to address the situation of sensitive information making it into the paging file. These attempts have been successful in some respects, but still fall short of the mark insofar as providing a system that is desirably secure and economical to use.
One past approach has been to designate certain pages of the main memory as “page locked,” and to place sensitive information only in page-locked pages. The “page locked” designation is a flag that tells the memory manager that the designated page is never to be moved to the paging file. While this ensures that the sensitive information does not make its way to the paging file, it consumes valuable main memory. Because there is a finite amount of main memory available, this approach is not optimal.
Another approach has been to configure the operating system to zero portions of the page file which are no longer associated with allocated memory when the operating system is shut down. This approach is problematic in the event that any of the following two events occurs: (1) power loss—induced or accidental, and (2) pages of memory are still allocated and active that contain sensitive information. In the former case, once power loss has occurred, an attacker can analyze the page file and “undo” any obfuscation as necessary. The operating system never had a change to zero the page file which would normally occur during clean shutdown of the operating system. In the latter case, if the pages of memory are still allocated and active, the operating system will be unable to zero the sensitive information that is contained in such pages.
Yet another approach has been to encrypt the sensitive information with a key that is hard-coded somewhere in the operating system. When the sensitive information is then sent to the hard disk, it will be encrypted and theoretically safe. This approach is not optimal because it is still subject to attack. Specifically, an attacker who accesses the hard disk need only look for data that appears to have been obfuscated with a key and then set about to break the key. Obfuscated or encrypted information can be recognized using a variety of approaches, for example, measuring the entropy of blocks of data. Once the key is broken, all of the encrypted information can be accessed. And, because the key is hard-coded, it never changes. Thus, once it is discovered by an attacker, the attacker can have access to all information that has been or will be encrypted using the hard-coded key.
This invention arose out of concerns associated with providing improved methods and systems for protecting information that is used in paging operating systems.